#include <brpc/server.h>
#include <butil/logging.h>
#include <regex>
#include <thread>
#include <iostream>
#include <iomanip>
#include <sstream>

#include "data/redis.hpp"
#include "channel.hpp"
#include "etcd.hpp"
#include "httplib.h"
#include "logger.hpp"

#include "base.pb.h"
#include "file.pb.h"
#include "friend.pb.h"
#include "gateway.pb.h"
#include "message.pb.h"
#include "notify.pb.h"
#include "transmite.pb.h"
#include "speech.pb.h"
#include "user.pb.h"

#include "connect.hpp"

namespace im{
    #define GET_PHONE_VERIFY_CODE   "/service/user/get_phone_verify_code"
    #define USERNAME_REGISTER       "/service/user/username_register"
    #define USERNAME_LOGIN          "/service/user/username_login"
    #define PHONE_REGISTER          "/service/user/phone_register"
    #define PHONE_LOGIN             "/service/user/phone_login"
    #define GET_USERINFO            "/service/user/get_user_info"
    #define SET_USER_AVATAR         "/service/user/set_avatar"
    #define SET_USER_NICKNAME       "/service/user/set_nickname"
    #define SET_USER_DESC           "/service/user/set_description"
    #define SET_USER_PHONE          "/service/user/set_phone"
    #define FRIEND_GET_LIST         "/service/friend/get_friend_list"
    #define FRIEND_APPLY            "/service/friend/add_friend_apply"
    #define FRIEND_APPLY_PROCESS    "/service/friend/add_friend_process"
    #define FRIEND_REMOVE           "/service/friend/remove_friend"
    #define FRIEND_SEARCH           "/service/friend/search_friend"
    #define FRIEND_GET_PENDING_EV   "/service/friend/get_pending_friend_events"
    #define CSS_GET_LIST            "/service/friend/get_chat_session_list"
    #define CSS_CREATE              "/service/friend/create_chat_session"
    #define CSS_GET_MEMBER          "/service/friend/get_chat_session_member"
    #define MSG_GET_RANGE           "/service/message_storage/get_history"
    #define MSG_GET_RECENT          "/service/message_storage/get_recent"
    #define MSG_KEY_SEARCH          "/service/message_storage/search_history"
    #define NEW_MESSAGE             "/service/message_transmit/new_message"
    #define FILE_GET_SINGLE         "/service/file/get_single_file"
    #define FILE_GET_MULTI          "/service/file/get_multi_file"
    #define FILE_PUT_SINGLE         "/service/file/put_single_file"
    #define FILE_PUT_MULTI          "/service/file/put_multi_file"
    #define SPEECH_RECOGNITION      "/service/speech/recognition"

    class GatewayServer {
        public:
            using ptr = std::shared_ptr<GatewayServer>;
            GatewayServer(int websocket_port, int http_port,
                const Discover::ptr& discover_client,
                const RedisPtr& redis_client, 
                const ServiceManager::ptr& mm_channels,
                const std::vector<std::string>& service_paths):
                _discover_client(discover_client),
                _redis_session(std::make_shared<Session>(redis_client)),
                _redis_status(std::make_shared<Status>(redis_client)),
                _connections(std::make_shared<Connection>()),
                _mm_channels(mm_channels){
                // 初始化服务名
                initServiceNames(service_paths);
                // 初始化websocket服务端口
                initWebsocketServer(websocket_port);
                // 初始化http服务
                initHttpServer(http_port);
            }

            void start(){
                _ws_server.run();
            }
        private:
            void initServiceNames(const std::vector<std::string> service_paths){
                std::vector<std::string> service_names{"文件子服务", "好友子服务", "消息存储子服务", "消息转发子服务", "用户子服务", "语音识别子服务"};
                for (int i = 0; i < service_paths.size(); i++) {
                    service_names_list.insert(std::make_pair(service_names[i], service_paths[i]));
                }
            }

            void initWebsocketServer(int port){
                _ws_server.set_access_channels(websocketpp::log::alevel::none); // 1.设置日志模式
                _ws_server.init_asio(); // 初始化为异步服务

                _ws_server.set_open_handler(std::bind(&GatewayServer::on_open, this, std::placeholders::_1));
                _ws_server.set_close_handler(std::bind(&GatewayServer::on_close, this, std::placeholders::_1));
                _ws_server.set_message_handler(std::bind(&GatewayServer::on_message, this, std::placeholders::_1, std::placeholders::_2));

                _ws_server.set_reuse_addr(true); // 设置地址重用
                _ws_server.listen(port);       // 设置监听端口
                _ws_server.start_accept();     // 开始监听
            }

            void initHttpServer(int port){
                _http_server.Post(GET_PHONE_VERIFY_CODE  , (httplib::Server::Handler)std::bind(&GatewayServer::GetPhoneVerifyCode         , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(USERNAME_REGISTER      , (httplib::Server::Handler)std::bind(&GatewayServer::UserRegister               , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(USERNAME_LOGIN         , (httplib::Server::Handler)std::bind(&GatewayServer::UserLogin                  , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(PHONE_REGISTER         , (httplib::Server::Handler)std::bind(&GatewayServer::PhoneRegister              , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(PHONE_LOGIN            , (httplib::Server::Handler)std::bind(&GatewayServer::PhoneLogin                 , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(GET_USERINFO           , (httplib::Server::Handler)std::bind(&GatewayServer::GetUserInfo                , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(SET_USER_AVATAR        , (httplib::Server::Handler)std::bind(&GatewayServer::SetUserAvatar              , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(SET_USER_NICKNAME      , (httplib::Server::Handler)std::bind(&GatewayServer::SetUserNickname            , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(SET_USER_DESC          , (httplib::Server::Handler)std::bind(&GatewayServer::SetUserDescription         , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(SET_USER_PHONE         , (httplib::Server::Handler)std::bind(&GatewayServer::SetUserPhoneNumber         , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(FRIEND_GET_LIST        , (httplib::Server::Handler)std::bind(&GatewayServer::GetFriendList              , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(FRIEND_APPLY           , (httplib::Server::Handler)std::bind(&GatewayServer::FriendAdd                  , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(FRIEND_APPLY_PROCESS   , (httplib::Server::Handler)std::bind(&GatewayServer::FriendAddProcess           , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(FRIEND_REMOVE          , (httplib::Server::Handler)std::bind(&GatewayServer::FriendRemove               , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(FRIEND_SEARCH          , (httplib::Server::Handler)std::bind(&GatewayServer::FriendSearch               , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(FRIEND_GET_PENDING_EV  , (httplib::Server::Handler)std::bind(&GatewayServer::GetPendingFriendEventList  , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(CSS_GET_LIST           , (httplib::Server::Handler)std::bind(&GatewayServer::GetChatSessionList         , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(CSS_CREATE             , (httplib::Server::Handler)std::bind(&GatewayServer::ChatSessionCreate          , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(CSS_GET_MEMBER         , (httplib::Server::Handler)std::bind(&GatewayServer::GetChatSessionMember       , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(MSG_GET_RANGE          , (httplib::Server::Handler)std::bind(&GatewayServer::GetHistoryMsg              , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(MSG_GET_RECENT         , (httplib::Server::Handler)std::bind(&GatewayServer::GetRecentMsg               , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(MSG_KEY_SEARCH         , (httplib::Server::Handler)std::bind(&GatewayServer::MsgSearch                  , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(NEW_MESSAGE            , (httplib::Server::Handler)std::bind(&GatewayServer::NewMessage                 , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(FILE_GET_SINGLE        , (httplib::Server::Handler)std::bind(&GatewayServer::GetSingleFile              , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(FILE_GET_MULTI         , (httplib::Server::Handler)std::bind(&GatewayServer::GetMultiFile               , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(FILE_PUT_SINGLE        , (httplib::Server::Handler)std::bind(&GatewayServer::PutSingleFile              , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(FILE_PUT_MULTI         , (httplib::Server::Handler)std::bind(&GatewayServer::PutMultiFile               , this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(SPEECH_RECOGNITION     , (httplib::Server::Handler)std::bind(&GatewayServer::SpeechRecognition          , this, std::placeholders::_1, std::placeholders::_2));
                
                _http_thread = std::thread([this, port](){
                    _http_server.listen("0.0.0.0", port);
                });
                _http_thread.detach();
            }

            /// @brief websocket服务 连接保活，发送心跳包
            void keepAlive(server::connection_ptr conn){
                if(!conn || conn->get_state() != websocketpp::session::state::value::open){
                    LOG_DEBUG("非正常连接状态，结束连接保活");
                    return;
                }
                conn->ping("");
                _ws_server.set_timer(60000, std::bind(&GatewayServer::keepAlive, this, conn));
            }

            /// @brief websocket服务 连接时 触发的回调函数
            /// @param hdl 连接句柄
            /// @return void
            void on_open(websocketpp::connection_hdl hdl){
                LOG_DEBUG("websocket长连接建立成功 {}", (size_t)_ws_server.get_con_from_hdl(hdl).get());
            }

            /// @brief websocket服务断开时，关闭长连接，并删除会话ID、状态、长连接资源
            /// @param hdl 连接句柄
            /// @return void
            void on_close(websocketpp::connection_hdl hdl){
                server::connection_ptr conn = _ws_server.get_con_from_hdl(hdl);
                std::string uid, ssid;
                if(false == _connections->client(conn, uid, ssid)){
                    LOG_WARN("长连接断开，未找到长连接对应的客户端信息！");
                    LOG_DEBUG("调试 用户ID{} 验证ID{}", uid, ssid);
                    return;
                }
                _redis_session->remove(ssid);
                _redis_status->remove(uid);
                _connections->remove(conn);
                LOG_INFO("websocket长连接断开成功 {}", uid);
            }

            /// @brief websocket服务  收到第一条消息后，根据消息中的会话ID进行身份识别，将客户端长连接添加管理
            /// @param hdl 连接句柄
            /// @return void
            void on_message(websocketpp::connection_hdl hdl, server::message_ptr msg){
                // 获取通信连接
                auto conn = _ws_server.get_con_from_hdl(hdl);
                ClientAuthenticationReq request;
                // 对消息进行反序列化
                if(false == request.ParseFromString(msg->get_payload())){
                    LOG_WARN("长连接身份识别失败：正文反序列化失败！");
                    return ;
                }
                // 验证 session_id
                std::string ssid = request.session_id();
                auto uid = _redis_session->uid(ssid);
                if (!uid) {
                    LOG_CRITICAL("长连接身份识别失败：未找到会话信息 {}！", ssid);
                    _ws_server.close(hdl, websocketpp::close::status::unsupported_data, "未找到会话信息!");
                    return;
                }
                _connections->insert(conn, *uid, ssid);
                LOG_DEBUG("新增长连接管理：{}-{}-{}", ssid, *uid, (size_t)conn.get());
                keepAlive(conn);
            }

            /*----------------------------------用户子服务-------------------------------------*/
            /// @brief 转发验证码信息
            void GetPhoneVerifyCode(const httplib::Request &request, httplib::Response &response){
                // 对数据进行反序列化
                PhoneVerifyCodeReq req;
                PhoneVerifyCodeRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    rsp.set_verify_code_id("");
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "验证信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                // 发送远程调用
                auto choose = _mm_channels->choose(service_names_list["用户子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的用户子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                UserService_Stub stub(choose.get());
                stub.GetPhoneVerifyCode(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "用户子服务调用失败！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                // 得到用户子服务的响应后，将响应内容进行序列化作为http响应正文
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            void UserRegister(const httplib::Request &request, httplib::Response &response){
                // 1.对数据进行反序列化
                UserRegisterReq req;
                UserRegisterRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "用户名注册信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                // 2.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["用户子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的用户子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                UserService_Stub stub(choose.get());
                stub.UserRegister(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "用户子服务调用失败！";
                    LOG_CRITICAL("{} {}失败原因:{}", req.request_id(), msg, cntl.ErrorText());
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                // 3.将响应内容进行序列化作为http响应正文
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            void UserLogin(const httplib::Request &request, httplib::Response &response){
                // 1.对数据进行反序列化
                UserLoginReq req;
                UserLoginRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    rsp.set_login_session_id("");
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "用户名登入信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    return err_response(req.request_id(), msg);
                }
                // 2.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["用户子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的用户子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                UserService_Stub stub(choose.get());
                stub.UserLogin(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "用户子服务调用失败！";
                    LOG_CRITICAL("{} {}失败原因:{}", req.request_id(), msg, cntl.ErrorText());
                    return err_response(req.request_id(), msg);
                }
                // 3.将响应内容进行序列化作为http响应正文
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            void PhoneRegister(const httplib::Request &request, httplib::Response &response){
                // 1.对数据进行反序列化
                PhoneRegisterReq req;
                PhoneRegisterRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "手机号注册信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                // 2.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["用户子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的用户子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                UserService_Stub stub(choose.get());
                stub.PhoneRegister(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "用户子服务调用失败！";
                    LOG_CRITICAL("{} {}失败原因:{}", req.request_id(), msg, cntl.ErrorText());
                    // LOG_CRITICAL("{} {}", req.request_id(), msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                // 3.将响应内容进行序列化作为http响应正文
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            void PhoneLogin(const httplib::Request &request, httplib::Response &response){
                // 1.对数据进行反序列化
                PhoneLoginReq req;
                PhoneLoginRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    rsp.set_login_session_id("");
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "手机号登入信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                // 2.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["用户子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的用户子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                UserService_Stub stub(choose.get());
                stub.PhoneLogin(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "用户子服务调用失败！";
                    LOG_CRITICAL("{} {}失败原因:{}", req.request_id(), msg, cntl.ErrorText());
                    // LOG_CRITICAL("{} {}", req.request_id(), msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                // 3.将响应内容进行序列化作为http响应正文
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            void GetUserInfo(const httplib::Request &request, httplib::Response &response){
                // 1.对数据进行反序列化
                GetUserInfoReq req;
                GetUserInfoRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "用户信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                // 1.5 在redis缓存中寻找session_id和是否存在，进行权限验证
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} - {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);  // 设置用户id
                // 2.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["用户子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的用户子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                UserService_Stub stub(choose.get());
                stub.GetUserInfo(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "用户子服务调用失败！";
                    LOG_CRITICAL("{} {}失败原因:{}", req.request_id(), msg, cntl.ErrorText());
                    // LOG_CRITICAL("{} {}", req.request_id(), msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                // 3.将响应内容进行序列化作为http响应正文
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            void SetUserAvatar(const httplib::Request &request, httplib::Response &response){
                // 1.对数据进行反序列化
                SetUserAvatarReq req;
                SetUserAvatarRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "设置用户头像信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                // 1.5 在redis缓存中寻找session_id和是否存在，进行权限验证
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} - {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);  // 设置用户id
                // 2.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["用户子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的用户子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                UserService_Stub stub(choose.get());
                stub.SetUserAvatar(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "用户子服务调用失败！";
                    LOG_CRITICAL("{} {}失败原因:{}", req.request_id(), msg, cntl.ErrorText());
                    // LOG_CRITICAL("{} {}", req.request_id(), msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                // 3.将响应内容进行序列化作为http响应正文
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            void SetUserNickname(const httplib::Request &request, httplib::Response &response){
                // 1.对数据进行反序列化
                SetUserNicknameReq req;
                SetUserNicknameRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "设置用户昵称信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                // 1.5 在redis缓存中寻找session_id和是否存在，进行权限验证
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} - {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);  // 设置用户id
                // 2.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["用户子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的用户子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                UserService_Stub stub(choose.get());
                stub.SetUserNickname(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "用户子服务调用失败！";
                    LOG_CRITICAL("{} {}失败原因:{}", req.request_id(), msg, cntl.ErrorText());
                    // LOG_CRITICAL("{} {}", req.request_id(), msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                // 3.将响应内容进行序列化作为http响应正文
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            void SetUserDescription(const httplib::Request &request, httplib::Response &response){
                // 1.对数据进行反序列化
                SetUserDescriptionReq req;
                SetUserDescriptionRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "设置用户签名信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                // 1.5 在redis缓存中寻找session_id和是否存在，进行权限验证
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} - {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);  // 设置用户id
                // 2.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["用户子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的用户子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                UserService_Stub stub(choose.get());
                stub.SetUserDescription(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "用户子服务调用失败！";
                    LOG_CRITICAL("{} {}失败原因:{}", req.request_id(), msg, cntl.ErrorText());
                    // LOG_CRITICAL("{} {}", req.request_id(), msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                // 3.将响应内容进行序列化作为http响应正文
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            void SetUserPhoneNumber(const httplib::Request &request, httplib::Response &response){
                // 1.对数据进行反序列化
                SetUserPhoneNumberReq req;
                SetUserPhoneNumberRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "设置用户手机号信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                // 1.5 在redis缓存中寻找session_id和是否存在，进行权限验证
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} - {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);  // 设置用户id
                // 2.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["用户子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的用户子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                UserService_Stub stub(choose.get());
                stub.SetUserPhoneNumber(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "用户子服务调用失败！";
                    LOG_CRITICAL("{} {}失败原因:{}", req.request_id(), msg, cntl.ErrorText());
                    // LOG_CRITICAL("{} {}", req.request_id(), msg);
                    response.set_content(msg, "application/x-protbuf");
                    return err_response(req.request_id(), msg);
                }
                // 3.将响应内容进行序列化作为http响应正文
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            
            /*----------------------------------好友子服务-------------------------------------*/
            void GetFriendList(const httplib::Request &request, httplib::Response &response){
                // 1.对数据进行反序列化
                GetFriendListReq req;
                GetFriendListRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "获取好友列表信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    return err_response(req.request_id(), msg);
                }
                // 1.5 在redis缓存中寻找session_id和是否存在，进行权限验证
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} - {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);  // 设置用户id
                // 2.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["好友子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的好友子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                FriendService_Stub stub(choose.get());
                stub.GetFriendList(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "好友子服务调用失败！";
                    LOG_CRITICAL("{} {}失败原因:{}", req.request_id(), msg, cntl.ErrorText());
                    // LOG_CRITICAL("{} {}", req.request_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                
                // 3.将响应内容进行序列化作为http响应正文
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            std::shared_ptr<GetUserInfoRsp> _GetUserInfo(const std::string& rid, const std::string& uid){
                GetUserInfoReq req;
                auto rsp = std::make_shared<GetUserInfoRsp>();
                req.set_request_id(rid);
                req.set_user_id(uid);
                
                // 2.转发调用
                auto choose = _mm_channels->choose(service_names_list["用户子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的用户子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    return std::shared_ptr<GetUserInfoRsp>();
                }
                brpc::Controller cntl;
                UserService_Stub stub(choose.get());
                stub.GetUserInfo(&cntl, &req, rsp.get(), nullptr);
                if(cntl.Failed()){
                    std::string msg = "用户子服务调用失败！";
                    LOG_CRITICAL("{} {}失败原因:{}", req.request_id(), msg, cntl.ErrorText());
                    // LOG_CRITICAL("{} {}", req.request_id(), msg);
                    return std::shared_ptr<GetUserInfoRsp>();
                }
                return rsp;
            }
            void FriendAdd(const httplib::Request &request, httplib::Response &response){
                LOG_INFO("收到来自{}的好友申请请求，转发给{}", request.remote_addr, "好友子服务");
                // 1.对数据进行反序列化
                FriendAddReq req;
                FriendAddRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "好友申请信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    return err_response(req.request_id(), msg);
                }
                // 2.在redis缓存中寻找session_id和是否存在，进行权限验证
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} - {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);
                // 3.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["好友子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的好友子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                FriendService_Stub stub(choose.get());
                stub.FriendAdd(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "好友子服务调用失败！";
                    LOG_CRITICAL("{} {}:{}", req.request_id(), msg, cntl.ErrorText());
                    return err_response(req.request_id(), msg);
                }
                // 4. 若业务处理成功 --- 且获取被申请方长连接成功，则向被申请放进行好友申请事件通知
                auto conn = _connections->connection(req.respondent_id());
                if(rsp.success() && conn){
                    auto user_rsp = _GetUserInfo(req.request_id(), *uid);
                    if (!user_rsp) {
                        LOG_CRITICAL("{} 获取当前客户端用户信息失败！", req.request_id());
                        return err_response(req.request_id(), "获取当前客户端用户信息失败！");
                    }
                    NotifyMessage notify_msg;
                    notify_msg.set_notify_type(NotifyType::FRIEND_ADD_APPLY_NOTIFY);
                    notify_msg.mutable_friend_add_apply()->mutable_user_info()->CopyFrom(user_rsp->user_info());
                    conn->send(notify_msg.SerializeAsString(), websocketpp::frame::opcode::value::binary);
                }
                // 5. 向客户端进行响应
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            void FriendAddProcess(const httplib::Request &request, httplib::Response &response){
                LOG_INFO("收到来自{}的“好友申请处理”请求，转发给{}", request.remote_addr, "好友子服务");
                // 1.对数据进行反序列化
                FriendAddProcessReq req;
                FriendAddProcessRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "好友申请信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    return err_response(req.request_id(), msg);
                }

                // 2. 客户端身份识别与鉴权
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} - {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);
                // 3. 将请求转发给好友子服务进行业务处理
                auto choose = _mm_channels->choose(service_names_list["好友子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的好友子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                FriendService_Stub stub(choose.get());
                stub.FriendAddProcess(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "好友子服务节点处理请求失败！";
                    LOG_CRITICAL("{} {}:{}", req.request_id(), msg, cntl.ErrorText());
                    return err_response(req.request_id(), msg);
                }
                // 响应处理完毕
                if(rsp.success()){
                    auto apply_conn = _connections->connection(req.apply_user_id());
                    auto process_conn = _connections->connection(*uid);
                    if (apply_conn) {
                        auto process_user_rsp = _GetUserInfo(req.request_id(), *uid);
                        if(process_user_rsp == nullptr){
                            LOG_CRITICAL("{} 获取被申请人信息失败！", req.request_id());
                            return err_response(req.request_id(), "获取被申请人信息失败！");
                        }
                        // 4.如果被申请人同意申请为好友，则创建单聊会话，需要对双方进行会话创建的通知
                        if(req.agree()){
                            NotifyMessage notify_apply;
                            notify_apply.set_notify_type(NotifyType::CHAT_SESSION_CREATE_NOTIFY);
                            auto chat_session = notify_apply.mutable_new_chat_session_info()->mutable_chat_session_info();
                            chat_session->set_single_chat_friend_id(*uid);
                            chat_session->set_chat_session_id(req.session_id());
                            chat_session->set_chat_session_name(process_user_rsp->user_info().nickname());
                            chat_session->set_avatar(process_user_rsp->user_info().avatar());
                            apply_conn->send(notify_apply.SerializeAsString(), websocketpp::frame::opcode::value::binary);
                            LOG_DEBUG("对申请人进行申请处理结果通知！");
                        }
                        NotifyMessage notify;
                        notify.set_notify_type(NotifyType::FRIEND_ADD_PROCESS_NOTIFY);
                        auto process_result = notify.mutable_friend_process_result();
                        process_result->mutable_user_info()->CopyFrom(process_user_rsp->user_info());
                        process_result->set_agree(req.agree());
                        apply_conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
                        LOG_DEBUG("给申请人推送申请处理结果通知！");
                    }
                    // 通知被申请人的会话创建消息
                    if(req.agree() && process_conn){
                        auto apply_user_rsp = _GetUserInfo(req.request_id(), req.apply_user_id());
                        if(apply_user_rsp == nullptr){
                            LOG_CRITICAL("{} 获取申请人信息失败！", req.request_id());
                            return err_response(req.request_id(), "获取申请人信息失败！");
                        }
                        NotifyMessage notify_process;
                        notify_process.set_notify_type(NotifyType::CHAT_SESSION_CREATE_NOTIFY);
                        auto chat_session = notify_process.mutable_new_chat_session_info()->mutable_chat_session_info();
                        chat_session->set_single_chat_friend_id(req.apply_user_id());
                        chat_session->set_chat_session_id(req.session_id());
                        chat_session->set_chat_session_name(apply_user_rsp->user_info().nickname());
                        LOG_DEBUG("会话ID:{}, 会话名称：{}",chat_session->chat_session_id(), chat_session->chat_session_name());
                        chat_session->set_avatar(apply_user_rsp->user_info().avatar());
                        process_conn->send(notify_process.SerializeAsString(), websocketpp::frame::opcode::value::binary);
                        LOG_DEBUG("对被申请人进行申请处理结果通知！");
                    }
                }
                //6. 对客户端进行响应
                response.set_content(rsp.SerializeAsString(), "application/x-protobuf");
            }
            void FriendRemove(const httplib::Request &request, httplib::Response &response){
                LOG_INFO("收到来自{}的好友删除请求，转发给{}", request.remote_addr, "好友子服务");
                // 1.对数据进行反序列化
                FriendRemoveReq req;
                FriendRemoveRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "好友删除信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    return err_response(req.request_id(), msg);
                }
                // 2.在redis缓存中寻找session_id和是否存在，进行权限验证
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} - {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);
                // 3.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["好友子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的好友子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                FriendService_Stub stub(choose.get());
                stub.FriendRemove(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "好友子服务调用失败！";
                    LOG_CRITICAL("{} {}:{}", req.request_id(), msg, cntl.ErrorText());
                    return err_response(req.request_id(), msg);
                }
                // 4. 若业务处理成功 --- 且获取被申请方长连接成功，则向申请人好友删除事件通知
                auto conn = _connections->connection(req.peer_id());
                if(rsp.success() && conn){
                    NotifyMessage notify_msg;
                    notify_msg.set_notify_type(NotifyType::FRIEND_REMOVE_NOTIFY);
                    notify_msg.mutable_friend_remove()->set_user_id(*uid);
                    conn->send(notify_msg.SerializeAsString(), websocketpp::frame::opcode::value::binary);
                }
                // 5. 向客户端进行响应
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            void FriendSearch(const httplib::Request &request, httplib::Response &response){
                LOG_INFO("收到来自{}的好友搜索请求，转发给{}", request.remote_addr, "好友子服务");
                // 1.对数据进行反序列化
                FriendSearchReq req;
                FriendSearchRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "好友搜索信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    return err_response(req.request_id(), msg);
                }
                // 2.在redis缓存中寻找session_id和是否存在，进行权限验证
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} - {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);
                // 3.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["好友子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的好友子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                FriendService_Stub stub(choose.get());
                stub.FriendSearch(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "好友子服务调用失败！";
                    LOG_CRITICAL("{} {}:{}", req.request_id(), msg, cntl.ErrorText());
                    return err_response(req.request_id(), msg);
                }
                // 4. 向客户端进行响应
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            void GetPendingFriendEventList(const httplib::Request &request, httplib::Response &response){
                LOG_INFO("收到来自{}的“获取好友申请列表”请求，转发给{}", request.remote_addr, "好友子服务");
                // 1.对数据进行反序列化
                GetPendingFriendEventListReq req;
                GetPendingFriendEventListRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "好友申请列表信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    return err_response(req.request_id(), msg);
                }
                // 2.在redis缓存中寻找session_id和是否存在，进行权限验证
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} - {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);
                // 3.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["好友子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的好友子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                FriendService_Stub stub(choose.get());
                stub.GetPendingFriendEventList(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "好友子服务调用失败！";
                    LOG_CRITICAL("{} {}:{}", req.request_id(), msg, cntl.ErrorText());
                    return err_response(req.request_id(), msg);
                }
                // 4. 向客户端进行响应
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            void GetChatSessionList(const httplib::Request &request, httplib::Response &response){
                LOG_INFO("收到来自{}的“获取会话列表”请求，转发给{}", request.remote_addr, "好友子服务");
                // 1.对数据进行反序列化
                GetChatSessionListReq req;
                GetChatSessionListRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "“获取会话列表”信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    return err_response(req.request_id(), msg);
                }
                // 2.在redis缓存中寻找session_id和是否存在，进行权限验证
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} - {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);
                // 3.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["好友子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的好友子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                FriendService_Stub stub(choose.get());
                stub.GetChatSessionList(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "好友子服务调用失败！";
                    LOG_CRITICAL("{} {}:{}", req.request_id(), msg, cntl.ErrorText());
                    return err_response(req.request_id(), msg);
                }
                // 4. 向客户端进行响应
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            void ChatSessionCreate(const httplib::Request &request, httplib::Response &response){
                LOG_INFO("收到来自{}的会话创建请求，转发给{}", request.remote_addr, "好友子服务");
                // 1.对数据进行反序列化
                ChatSessionCreateReq req;
                ChatSessionCreateRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "创建群聊会话信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    return err_response(req.request_id(), msg);
                }
                // 2.在redis缓存中寻找session_id和是否存在，进行权限验证
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} - {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);
                // 3.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["好友子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的好友子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                FriendService_Stub stub(choose.get());
                stub.ChatSessionCreate(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "好友子服务调用失败！";
                    LOG_CRITICAL("{} {}:{}", req.request_id(), msg, cntl.ErrorText());
                    return err_response(req.request_id(), msg);
                }
                if(rsp.success()){
                    for(auto muid : req.member_id_list()){
                        auto conn = _connections->connection(muid);
                        if(conn == nullptr){
                            LOG_DEBUG("未找到群聊成员 {} 长连接", muid);
                            continue;
                        }
                        NotifyMessage notify_msg;
                        notify_msg.set_notify_type(NotifyType::CHAT_SESSION_CREATE_NOTIFY);
                        auto chat_session = notify_msg.mutable_new_chat_session_info()->mutable_chat_session_info();
                        chat_session->CopyFrom(rsp.chat_session_info());
                        conn->send(notify_msg.SerializeAsString(), websocketpp::frame::opcode::value::binary);
                    }
                }
                rsp.clear_chat_session_info();  // 减少响应的体积
                // 4. 向客户端进行响应
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            void GetChatSessionMember(const httplib::Request &request, httplib::Response &response){
                LOG_INFO("收到来自{}的获取会话成员请求，转发给{}", request.remote_addr, "好友子服务");
                // 1.对数据进行反序列化
                GetChatSessionMemberReq req;
                GetChatSessionMemberRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "获取好友列表信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    return err_response(req.request_id(), msg);
                }
                // 2.在redis缓存中寻找session_id和是否存在，进行权限验证
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} - {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);
                // 3.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["好友子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的好友子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                FriendService_Stub stub(choose.get());
                stub.GetChatSessionMember(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "好友子服务调用失败！";
                    LOG_CRITICAL("{} {}:{}", req.request_id(), msg, cntl.ErrorText());
                    return err_response(req.request_id(), msg);
                }
                // 4. 向客户端进行响应
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }

            /*----------------------------------消息存储子服务-------------------------------------*/
            void GetHistoryMsg(const httplib::Request &request, httplib::Response &response){
                // 1.对数据进行反序列化
                GetHistoryMsgReq req;
                GetHistoryMsgRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "获取历史消息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    return err_response(req.request_id(), msg);
                }
                auto s = req.start_time();
                auto o = req.over_time();
                std::string start_time = std::ctime(&s);
                std::string over_time = std::ctime(&o);
                // LOG_DEBUG("起始时间：{}，结束时间：{}",start_time, over_time);
                // 2.在redis缓存中寻找session_id和是否存在，进行权限验证
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} - {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);
                // 3.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["消息存储子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的消息存储子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                MsgStorageService_Stub stub(choose.get());
                stub.GetHistoryMsg(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "消息存储子服务调用失败！";
                    LOG_CRITICAL("{} {}:{}", req.request_id(), msg, cntl.ErrorText());
                    return err_response(req.request_id(), msg);
                }
                // 4. 向客户端进行响应
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            void GetRecentMsg(const httplib::Request &request, httplib::Response &response){
                // 1.对数据进行反序列化
                GetRecentMsgReq req;
                GetRecentMsgRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "获取最近信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    return err_response(req.request_id(), msg);
                }
                // 2.在redis缓存中寻找session_id和是否存在，进行权限验证
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} - {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);
                // 3.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["消息存储子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的消息存储子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                MsgStorageService_Stub stub(choose.get());
                stub.GetRecentMsg(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "消息存储子服务调用失败！";
                    LOG_CRITICAL("{} {}:{}", req.request_id(), msg, cntl.ErrorText());
                    return err_response(req.request_id(), msg);
                }
                // 4. 向客户端进行响应
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            void MsgSearch(const httplib::Request &request, httplib::Response &response){
                // 1.对数据进行反序列化
                MsgSearchReq req;
                MsgSearchRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "消息搜索的信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    return err_response(req.request_id(), msg);
                }
                LOG_DEBUG("MsgSearchReq: \n uid:{} \nsession_id:{} \nchat_session_id:{} \nsearch_key:{}",
                                req.user_id(), req.session_id(), req.chat_session_id(), req.search_key());
                // 2.在redis缓存中寻找session_id和是否存在，进行权限验证
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} -{} {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);
                // 3.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["消息存储子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的消息存储子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                MsgStorageService_Stub stub(choose.get());
                stub.MsgSearch(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "消息存储子服务调用失败！";
                    LOG_CRITICAL("{} {}:{}", req.request_id(), msg, cntl.ErrorText());
                    return err_response(req.request_id(), msg);
                }
                // 4. 向客户端进行响应
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            /*----------------------------------消息转发子服务-------------------------------------*/
            void NewMessage(const httplib::Request &request, httplib::Response &response){
                // 1.对数据进行反序列化
                NewMessageReq req;
                NewMessageRsp rsp;
                GetTransmitTargetRsp target_rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "创建群聊会话信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    return err_response(req.request_id(), msg);
                }
                // 2.在redis缓存中寻找session_id和是否存在，进行权限验证
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} - {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);
                // 3.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["消息转发子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的消息转发子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                MsgTransmitService_Stub stub(choose.get());
                stub.GetTransmitTarget(&cntl, &req, &target_rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "消息转发子服务调用失败！";
                    LOG_CRITICAL("{} {}:{}", req.request_id(), msg, cntl.ErrorText());
                    return err_response(req.request_id(), msg);
                }
                // 4. 若业务处理成功 --- 且获取被申请方长连接成功，则向被申请放进行好友申请事件通知
                if(target_rsp.success()){
                    for(auto tuid : target_rsp.target_id_list()){
                        if (tuid == *uid)
                            continue; //不通知自己
                        auto conn = _connections->connection(tuid);
                        if(conn == nullptr){
                            LOG_DEBUG("未找到要转发的成员 {} 长连接", tuid);
                            continue;
                        }
                        NotifyMessage notify_msg;
                        notify_msg.set_notify_type(NotifyType::CHAT_MESSAGE_NOTIFY);
                        auto msg_info = notify_msg.mutable_new_message_info()->mutable_message_info();
                        msg_info->CopyFrom(target_rsp.message());
                        conn->send(notify_msg.SerializeAsString(), websocketpp::frame::opcode::value::binary);
                    }
                }
                rsp.set_request_id(target_rsp.request_id());
                rsp.set_success(target_rsp.success());
                rsp.set_errmsg(target_rsp.errmsg());
                // 4. 向客户端进行响应
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf"); 
            }
            
            /*----------------------------------文件子服务-------------------------------------*/
            void GetSingleFile(const httplib::Request &request, httplib::Response &response){
                // 1.对数据进行反序列化
                GetSingleFileReq req;
                GetSingleFileRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "下载单个文件的信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    return err_response(req.request_id(), msg);
                }
                // 2.在redis缓存中寻找session_id和是否存在，进行权限验证
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} - {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);
                // 3.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["文件子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的文件子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                FileService_Stub stub(choose.get());
                stub.GetSingleFile(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "文件子服务调用失败！";
                    LOG_CRITICAL("{} {}:{}", req.request_id(), msg, cntl.ErrorText());
                    return err_response(req.request_id(), msg);
                }
                // 4. 向客户端进行响应
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            void GetMultiFile(const httplib::Request &request, httplib::Response &response){
                // 1.对数据进行反序列化
                GetMultiFileReq req;
                GetMultiFileRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "下载多个文件的信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    return err_response(req.request_id(), msg);
                }
                // 2.在redis缓存中寻找session_id和是否存在，进行权限验证
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} - {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);
                // 3.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["文件子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的文件子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                FileService_Stub stub(choose.get());
                stub.GetMultiFile(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "文件子服务调用失败！";
                    LOG_CRITICAL("{} {}:{}", req.request_id(), msg, cntl.ErrorText());
                    return err_response(req.request_id(), msg);
                }
                // 4. 向客户端进行响应
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            void PutSingleFile(const httplib::Request &request, httplib::Response &response){
                // 1.对数据进行反序列化
                PutSingleFileReq req;
                PutSingleFileRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "上传单个文件的信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    return err_response(req.request_id(), msg);
                }
                // 2.在redis缓存中寻找session_id和是否存在，进行权限验证
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} - {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);
                // 3.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["文件子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的文件子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                FileService_Stub stub(choose.get());
                stub.PutSingleFile(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "文件子服务调用失败！";
                    LOG_CRITICAL("{} {}:{}", req.request_id(), msg, cntl.ErrorText());
                    return err_response(req.request_id(), msg);
                }
                // 4. 向客户端进行响应
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            void PutMultiFile(const httplib::Request &request, httplib::Response &response){
                // 1.对数据进行反序列化
                PutMultiFileReq req;
                PutMultiFileRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "上传多个文件的信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    return err_response(req.request_id(), msg);
                }
                // 2.在redis缓存中寻找session_id和是否存在，进行权限验证
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} - {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);
                // 3.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["文件子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的文件子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                FileService_Stub stub(choose.get());
                stub.PutMultiFile(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "文件子服务调用失败！";
                    LOG_CRITICAL("{} {}:{}", req.request_id(), msg, cntl.ErrorText());
                    return err_response(req.request_id(), msg);
                }
                // 4. 向客户端进行响应
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
            /*----------------------------------语音识别子服务-------------------------------------*/
            void SpeechRecognition(const httplib::Request &request, httplib::Response &response){
                // 1.对数据进行反序列化
                SpeechRecognitionReq req;
                SpeechRecognitionRsp rsp;
                auto err_response = [&rsp, &response](const std::string& rid, const std::string& msg){
                    rsp.set_request_id(rid);
                    rsp.set_success(false);
                    rsp.set_errmsg(msg);
                    response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
                };
                bool ret = req.ParseFromString(request.body);   // 验证信息反序列化
                if(!ret){
                    std::string msg = "语音转文字信息反序列化失败！";
                    LOG_CRITICAL("{}", msg);
                    return err_response(req.request_id(), msg);
                }
                // 2.在redis缓存中寻找session_id和是否存在，进行权限验证
                auto uid = _redis_session->uid(req.session_id());
                if(!uid){
                    std::string msg = "获取登录会话关联用户信息失败！";
                    LOG_CRITICAL("{} - {}", req.session_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                req.set_user_id(*uid);
                // 3.发送远程调用
                auto choose = _mm_channels->choose(service_names_list["语音识别子服务"]);
                if(choose == nullptr){
                    std::string msg = "未找到可提供业务处理的语音识别子服务节点！";
                    LOG_CRITICAL("{} {}", req.request_id(), msg);
                    return err_response(req.request_id(), msg);
                }
                brpc::Controller cntl;
                cntl.set_timeout_ms(10000); // 避免超时
                SpeechService_Stub stub(choose.get());
                stub.SpeechRecognition(&cntl, &req, &rsp, nullptr);
                if(cntl.Failed()){
                    std::string msg = "语音识别子服务调用失败！";
                    LOG_CRITICAL("{} {}:{}", req.request_id(), msg, cntl.ErrorText());
                    return err_response(req.request_id(), msg);
                }
                // 4. 向客户端进行响应
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            }
        private:
            Discover::ptr _discover_client;
            std::unordered_map<std::string, std::string> service_names_list;    // 需要服务的的服务

            Session::ptr _redis_session;
            Status::ptr _redis_status;
            ServiceManager::ptr _mm_channels;

            Connection::ptr _connections;

            server _ws_server;
            httplib::Server _http_server;
            std::thread _http_thread;
    };

    class GatewayServiceBuild{
        public:
            GatewayServiceBuild(){}

            void init_Redis_client(const std::string &host, int port, int db_num, bool keep_alive){
                _redis_client = RedisClientFactory::create(host, port, db_num, keep_alive);
            }

            void init_discovery_client(const std::string &reg_host,
                    const std::string &base_service_name,
                    std::vector<std::string> service_names) {
                _mm_channels = std::make_shared<ServiceManager>();
                for (auto &item : service_names) {
                    _mm_channels->declared(item);
                    LOG_DEBUG("设置子服务为需添加管理的子服务：{}", item);
                    _service_names.push_back(item);
                }
                auto put_cb = std::bind(&ServiceManager::onServiceOnline, _mm_channels.get(), std::placeholders::_1, std::placeholders::_2);
                auto del_cb = std::bind(&ServiceManager::onServiceOffline, _mm_channels.get(), std::placeholders::_1, std::placeholders::_2);
                _discover_client = std::make_shared<Discover>(reg_host, base_service_name, put_cb, del_cb);
            }

            void init_server_port(int websocket_port, int http_port) {
                _websocket_port = websocket_port;
                _http_port = http_port;
            }
            
            GatewayServer::ptr build() {
                if (!_redis_client) {
                    LOG_CRITICAL("还未初始化Redis客户端模块！");
                    abort();
                }
                if (!_discover_client) {
                    LOG_CRITICAL("还未初始化服务发现模块！");
                    abort();
                }
                if (!_mm_channels) {
                    LOG_CRITICAL("还未初始化信道管理模块！");
                    abort();
                }
                return std::make_shared<GatewayServer>(
                        _websocket_port, _http_port, _discover_client, 
                        _redis_client, _mm_channels, _service_names
                    );
            }
        private:
            int _websocket_port = 0;
            int _http_port = 0;

            RedisPtr _redis_client;             // redis客户端
            Discover::ptr _discover_client;     // 服务发现客户端

            ServiceManager::ptr _mm_channels;   // 信道管理类
            std::vector<std::string> _service_names;    // 需要服务的的服务
    };
}